﻿using System;
using System.Collections.Generic;
using System.Linq;
using K9Nano.Dependency;
using K9Nano.Share.Exceptions;
using Microsoft.Extensions.DependencyInjection;

namespace K9Nano.Application.Features
{
    /// <summary>
    /// Implements <see cref="IFeatureManager"/>.
    /// </summary>
    internal class FeatureManager : FeatureDefinitionContextBase, IFeatureManager, ISingletonDependency
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly IFeatureConfiguration _featureConfiguration;

        public FeatureManager(IFeatureConfiguration featureConfiguration, IServiceProvider serviceProvider)
        {
            _featureConfiguration = featureConfiguration;
            _serviceProvider = serviceProvider;
        }

        /// <summary>
        /// Initializes this <see cref="FeatureManager"/>
        /// </summary>
        public void Initialize()
        {
            using var scope = _serviceProvider.CreateScope();

            foreach (var providerType in _featureConfiguration.Providers)
            {
                var provider = (FeatureProvider)scope.ServiceProvider.GetService(providerType);

                provider.SetFeatures(this);
            }

            Features.AddAllFeatures();
        }

        /// <summary>
        /// Gets a feature by its given name
        /// </summary>
        /// <param name="name">Name of the feature</param>
        public Feature Get(string name)
        {
            var feature = GetOrNull(name);
            if (feature == null)
            {
                throw new K9Exception("There is no feature with name: " + name);
            }

            return feature;
        }

        /// <summary>
        /// Gets all the features
        /// </summary>
        public IReadOnlyList<Feature> GetAll()
        {
            return Features.Values.ToList();
        }
    }
}
